<?php

include_once("admin/edit_block.php");
include_once("includes/addMessage.php");

class simpleTableEditor
{
    protected $tableName, $adminAction, $idField = '', $titleField = '', $fields = Array(), $data = Array(), $hasFileUploads;
    protected $renderQueue = Array(), $dataPresent = false, $welcomeInfo, $langName, $allowDelete, $allowAddition;

    function simpleTableEditor($tableName, $adminAction, $langName,  $welcomeInfo, $allowDelete = true, $hasFilesUploads = false, $allowAddition = true)
    {
        $this->tableName = $tableName;
        $this->adminAction = $adminAction;
        $this->langName = $langName;
        $this->welcomeInfo = $welcomeInfo;
        $this->allowDelete = $allowDelete;
        $this->hasFileUploads = $hasFilesUploads;
        $this->allowAddition = $allowAddition;
    }

    function addColumn($fieldObject)
    {
        if(is_subclass_of($fieldObject, 'editorField'))
        {
            $this->fields[$fieldObject->getFieldName()] = $fieldObject;
            $this->data[$fieldObject->getFieldName()] = '';
            //get id field
            if(is_a($fieldObject, 'fieldId') && $this->idField == '')
                    $this->idField = $fieldObject->getFieldName();
            elseif(is_a($fieldObject, 'fieldId') )
                throw new Exception("Invalid attempt to add second id field '" . $fieldObject->getFieldName() . "' to table: " . $this->tableName);


            //get title field
            if(is_a($fieldObject, 'fieldTitle') && $this->titleField == '')
                    $this->titleField = $fieldObject->getFieldName();
            elseif(is_a($fieldObject, 'fieldTitle') )
                throw new Exception("Invalid attempt to add second title field '" . $fieldObject->getFieldName() . "' to table: " . $this->tableName);


        }
        else
            throw new Exception("Invalid editor object passed for table: " . $this->tableName);
    }

    //we've setup the table now we do things!
    function doStuff()
    {
        global $lang;
        $this->renderQueue[] = new addMessage($this->welcomeInfo,$lang['AdminWelcomeTitle']);

        
        //Figure out what we need to do.
        if(isset($_POST['removeItem']) && isset($_POST['itemID']))
        {
            unset($_POST['removeItem']);
            $this->doDelete();
            $this->generateSelectionInput($_POST['itemID']);
        }
        else if(isset($_POST['editItem']) && isset($_POST['itemID']))
        {
            unset($_POST['editItem']);
            $this->getValuesFromId($_POST['itemID']);
            $this->generateSelectionInput($_POST['itemID']);
        }
        else if(isset($_POST['addRecord']))
        {
            $this->doAdd();
            unset($_POST['addRecord']);
            $this->generateSelectionInput($this->data[$this->idField]);
        }
        else if(isset($_POST['saveRecord']) && isset($_POST[$this->idField]))
        {
            unset($_POST['saveRecord']);
            $this->doEdit();
            $this->generateSelectionInput($this->data[$this->idField]);
        }
        else
            //generate selection module
            $this->generateSelectionInput();
        

    }

    private function generateSelectionInput($selectedId = -1)
    {
        $selectionOptions = $this->getSelectionOptions();

        if(isset($_POST['itemID']))
	{
		$this->renderQueue[] = (new edit_block($this->adminAction, $this->langName,
					         $selectionOptions["query"],
						 $selectionOptions["id"], $selectionOptions["text"], $selectionOptions["minor"], $this->allowDelete, $_POST['itemID']));
	}
	else
	{
		$this->renderQueue[] = (new edit_block($this->adminAction, $this->langName,
					         $selectionOptions["query"],
						 $selectionOptions["id"], $selectionOptions["text"], $selectionOptions["minor"], $this->allowDelete));
	}
    }

    protected function getSelectionOptions()
    {
        return array("query" => $this->getSimpleTitleOrderedSelectAllQuery(), "id" => $this->idField, "text" => $this->titleField, "minor" => "");
    }

    //gets value from post, clears the post and validates the values
    private function getValuesFromPost($ignoreId=false)
    {
        foreach ($this->data as $fieldName => $value) {
            if(array_key_exists ($fieldName, $_POST) && ($fieldName != $this->idField || !$ignoreId))
                {
                    $this->data[$fieldName] = $this->fields[$fieldName]->validateValue($_POST[$fieldName],$this->idField,$this->data);
                    unset($_POST[$fieldName]);
                }
            elseif(!$ignoreId && $this->fields[$fieldName]->isDatabaseField())
                throw new Exception("Could not find field '" . $fieldName . "' in POST array");
        }

        $this->postProcessFields();
        $this->dataPresent=true;
    }

    //gets id from post and then the rest from database
    private function getValuesFromId($id)
    {
        global $db;

        $this->data[$this->idField] = $this->fields[$this->idField]->validateValue($id);
        $query = $this->getSimpleSelectQuery($id);
        $result = $db->sql_query($query);
        if($row = $db->sql_fetchrow($result))
        {
            foreach ($row as $fieldName => $fieldValue)
            {
                if(array_key_exists ($fieldName, $this->data))
                {
                    $this->data[$fieldName] = $fieldValue;
                }
            }
        }

        $this->postProcessFields();
        $this->dataPresent = true;
    }

    private function getSimpleInsertQuery()
    {
        $query = "INSERT INTO " . $this->tableName;
        $columnList = " (";
        $valueList = " VALUES (";

        foreach ($this->fields as $fieldName => $field) {
            if($field->isDatabaseField() && $fieldName != $this->idField) {
                $columnList .= $fieldName . ", ";
                $valueList .= $field->getQueryValue($this->data[$fieldName]) . ", " ;
            }
        }
        $columnList = substr($columnList, 0, -2) . ")";
        $valueList = substr($valueList, 0, -2) . ")";

        return $query . $columnList . $valueList;
    }

    private function getSimpleUpdateQuery()
    {
        $query = "UPDATE " . $this->tableName . " SET ";

        foreach ($this->fields as $fieldName => $field) {
            if($field->isDatabaseField() && $fieldName != $this->idField) {
                $query .= $fieldName . " = " . $field->getQueryValue($this->data[$fieldName]) . ", " ;
            }
        }
        $query = substr($query, 0, -2);
        $query .= " WHERE " . $this->idField . " = " . $this->fields[$this->idField]->getQueryValue($this->data[$this->idField]);

        return $query;
    }

    private function getSimpleDeleteQuery($id)
    {
        return "DELETE FROM " . $this->tableName . " WHERE " . $this->idField . " = " . $id;
    }

    private function getSimpleSelectQuery($id)
    {
        return "SELECT * FROM " . $this->tableName . " WHERE " . $this->idField . " = " . $id;
    }

    private function getSimpleSelectAllQuery()
    {
        return "SELECT * FROM " . $this->tableName . " ORDER BY " . $this->idField . " ASC";
    }

    private function getSimpleTitleOrderedSelectAllQuery()
    {
        return "SELECT * FROM " . $this->tableName . " ORDER BY " . $this->titleField . " ASC";

    }

    private function doAdd()
    {
        global $db, $lang;

        $this->getValuesFromPost(true);
        $query = $this->getSimpleInsertQuery();
        
        $db->sql_query("LOCK TABLES ". $this->tableName . "  WRITE");
        $db->sql_query("SET AUTOCOMMIT = 0");
        $db->sql_query($query);
        $insertID = $db->sql_nextid();
        $db->sql_query("COMMIT");
        $db->sql_query("SET AUTOCOMMIT = 1");
        $db->sql_query("UNLOCK TABLES");

        $this->data[$this->idField] = $insertID;

        $this->customPostAddActions();

        $this->renderQueue[] = new addMessage(str_replace('{entry}', $this->data[$this->titleField], $lang['AdminAdded']), $lang['AdminAddedTitle']);
    }

    protected function customPostAddActions()
    {
    }

    private function doEdit()
    {
        global $db, $lang;

        $this->getValuesFromPost();
        $query = $this->getSimpleUpdateQuery($_POST['itemID']);
        $result = $db->sql_query($query);
        $this->customPostEditActions();

        $this->renderQueue[] = new addMessage(str_replace('{entry}', $this->data[$this->titleField], $lang['AdminUpdated']), $lang['AdminUpdatedTitle']);
    }

    protected function customPostEditActions()
    {
    }

    private function doDelete()
    {
        global $db, $lang;

        $this->getValuesFromId($_POST['itemID']);
        $this->dataPresent = false;
        $query = $this->getSimpleDeleteQuery($_POST['itemID']);
        $result = $db->sql_query($query);
        $this->customPostDeleteActions();
        $this->renderQueue[] = new addMessage(str_replace('{entry}', $this->data[$this->titleField], $lang['AdminRemoved']), $lang['AdminRemovedTitle']);
    }

    protected function customPostDeleteActions()
    {
    }

    //function carries out any post processing on fields after getting the data
    private function postProcessFields()
    {
        foreach ($this->fields as $field)
            $field->postProcess($this->data, $this->idField, $this->titleField);
    }

    function render()
    {
        global $lang, $skin_dir;

        foreach ($this->renderQueue as $item)
           $item->render();

        $action = $this->adminAction;

        //we have a record to show.
        if ($this->dataPresent)
        {
            $mess = new addMessage($lang['AdminEdit'], $lang['AdminEditTitle']);
            $mess->render();
            
            $enctype = $this->hasFileUploads ? 'enctype="multipart/form-data" ' : '';
            include $skin_dir . 'admin/fieldStart.tpl';

            foreach($this->fields as $fieldName => $field)
            {
                $field->renderEditor($skin_dir, $this->data[$fieldName]);
            }

            $submitText = $lang['SaveButton'];
            $submitValue = 'saveRecord';

            include $skin_dir . 'admin/fieldSave.tpl';

            include $skin_dir . 'admin/fieldEnd.tpl';
        }

        if($this->allowAddition)
        {
            //render add record box
            $mess = new addMessage($lang['AdminAdd'], $lang['AdminAddTitle']);
            $mess->render();

            $enctype = '';
            include $skin_dir . 'admin/fieldStart.tpl';

            foreach($this->fields as $fieldName => $field)
            {
                $field->renderEditor($skin_dir, '', true);
            }

            $submitText = $lang['AddButton'];
            $submitValue = 'addRecord';

            include $skin_dir . 'admin/fieldSave.tpl';

            include $skin_dir . 'admin/fieldEnd.tpl';
        }
    }
}
?>
